package com.dreamcar.auction.entity.eao;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.queries.ReadAllQuery;

import com.dreamcar.auction.entity.Bid;
import com.dreamcar.auction.entity.CarModel;
import com.dreamcar.auction.entity.Component;
import com.dreamcar.auction.entity.DestinationMarket;
import com.dreamcar.auction.entity.DreamcarEmployee;
import com.dreamcar.auction.entity.LogUtil;
import com.dreamcar.auction.entity.PurchaseOrder;
import com.dreamcar.auction.entity.Request;
import com.dreamcar.auction.entity.Supplier;

@Stateless
public class ReverseAuctionEAO implements ReverseAuctionEAOLocal{

	@PersistenceContext
	private EntityManager entityManager;
	
	//****Consultas para filtrar Componentes ***//
	
	public List<DestinationMarket> findAllDestinationMarket() {
		LogUtil.log("finding all DestinationMarket instances", Level.INFO,
				null);
		try {
			final String queryString = "select model from DestinationMarket model";
			Query query = entityManager.createQuery(queryString);
			return query.getResultList();
		} catch (RuntimeException re) {
			LogUtil.log("find all failed", Level.SEVERE, re);
			throw re;
		}
	}
	
	public List<CarModel> findCarModelByDestinationMarket(
			Integer idDestinationMarket) {
		LogUtil.log("finding CarModel instance by idDestinationMarket: ", Level.INFO, null);

		try {
			Set<CarModel> setCars = entityManager.find(DestinationMarket.class, idDestinationMarket).getCarModels();
			ArrayList<CarModel> arCarModels = new ArrayList<CarModel>(setCars);
			return arCarModels;
		} catch (RuntimeException re) {
			LogUtil.log("find by property name failed", Level.SEVERE, re);
			throw re;
		}
	}
	
	public List<Component> findCarComponentByCarModel(Integer idCarModel, String discriminator) {
		try {
			Query query = entityManager.createQuery("select comp from Component comp where comp.discriminator=:discriminator and :carModel member of comp.carModels");
			query.setParameter("discriminator", discriminator);
			query.setParameter("carModel", entityManager.find(CarModel.class, idCarModel));
			return query.getResultList();
		} catch (RuntimeException re) {
			LogUtil.log("find by property name failed", Level.SEVERE, re);
			throw re;
		}
	}
	//****Terminan Consultas para filtrar Componentes ***//
	
	
	
	public void saveRequest(Request request, Integer idComponent, String username) {
		LogUtil.log("saving Request instance", Level.INFO, null);
		try {
			final String queryString = "select model from DreamcarEmployee model where model.username"
				+ "= :propertyValue";
			Query query = entityManager.createQuery(queryString);
			query.setParameter("propertyValue", username);
			DreamcarEmployee employee = (DreamcarEmployee)query.getSingleResult();
			request.setDreamcarEmployee(employee);

			request.setComponent(entityManager.find(Component.class, idComponent));
			entityManager.persist(request);
			LogUtil.log("save successful", Level.INFO, null);
		} catch (RuntimeException re) {
			LogUtil.log("save failed", Level.SEVERE, re);
			throw re;
		}
	}
	
	//mover a base
	public Request updateRequest(Request entity) {
		LogUtil.log("updating Request instance", Level.INFO, null);
		try {
			Request result = entityManager.merge(entity);
			LogUtil.log("update successful", Level.INFO, null);
			return result;
		} catch (RuntimeException re) {
			LogUtil.log("update failed", Level.SEVERE, re);
			throw re;
		}
	}

	public Set<Bid> findBidsByRequest(Integer requestId){
		try {
			Request request = entityManager.find(Request.class, requestId);
			entityManager.refresh(request);
			return request.getBids();
		} catch (RuntimeException re) {
			LogUtil.log("find by property name failed", Level.SEVERE, re);
			throw re;
		}
	}
	
	
	public Request getRequestReferenceById(Integer idRequest){
		return entityManager.getReference(Request.class, idRequest);
	}
	
	//mover a base
	public void saveBid(Bid bid, String username){
		Supplier supplier = findSupplierByUsername(username);
		bid.setSupplier(supplier);
		try {
			entityManager.persist(bid);
		} catch (RuntimeException re) {
			LogUtil.log("save failed", Level.SEVERE, re);
			throw re;
		}
	}
	
	public PurchaseOrder savePO(Integer requestId, Integer bidId){
		PurchaseOrder po = new PurchaseOrder();
		Request request = entityManager.getReference(Request.class, requestId);
		Bid bid = entityManager.getReference(Bid.class, bidId);
		po.setRequest(request);
		po.setBid(bid);
		po.setDate(new java.sql.Date(new Date().getTime()));
		entityManager.persist(po);
		return po;
	}
	
	public Supplier findSupplierByUsername(String username){
		return (Supplier) entityManager.createQuery("select sup from Supplier sup where sup.username=:username")
		.setParameter("username", username)
		.getSingleResult();
	}

	//mover a base
	@Override
	public Bid updateBid(Bid bid) {
		try {
			Bid result = entityManager.merge(bid);
			LogUtil.log("update successful", Level.INFO, null);
			return result;
		} catch (RuntimeException re) {
			LogUtil.log("update failed", Level.SEVERE, re);
			throw re;
		}
	}
	
	@Override
	public List<Request> findRequestByExample(Request request) {
		ReadAllQuery query = new ReadAllQuery(Request.class);
		query.setExampleObject(request);
		Query query2 = JpaHelper.createQuery(query, entityManager);
		List<Request> lstRequest = query2.getResultList();
		return lstRequest;
	}
	
	public Component getComponentReferenceById(Integer componentId){
		try {
			return entityManager.getReference(Component.class, componentId);
		} catch (RuntimeException re) {
			LogUtil.log("save failed", Level.SEVERE, re);
			throw re;
		}
	}

}
